<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h2>一、场景复现</h2>
  <div>比如一个数 1÷3=0.33333333......</div>
  <br>
  <div>这是一个除不尽的运算，3会一直无限循环，数学可以表示，但是计算机要存储，方便下次再使用，但0.333333...... 这个数无限循环，再大的内存它也存不下，所以不能存储一个相对于数学来说的值，只能存储一个近似值，这么存储后再取出时自然就出现精度丢失问题</div>
  <script>
    console.log(0.1 + 0.2);
  </script>
  <h2>二、浮点数</h2>
  <div>“浮点数”是一种表示数字的标准，整数也可以用浮点数的格式来存储,也可以理解成，浮点数就是小数</div>
  <br>
  <div>JS 最多能表示的精度是 16</div>
  <h2>小结</h2>
  <div>
    计算机存储双精度浮点数需要先把十进制数转换为二进制的科学记数法的形式，然后计算机以自己的规则存储二进制的科学记数法,因为存储时有位数限制（64位），并且某些十进制的浮点数在转换为二进制数时会出现无限循环，会造成二进制的舍入操作(0舍1入)，当再转换为十进制时就造成了计算误差
  </div>
  <h2>三、解决方案</h2>
  <div>理论上用有限的空间来存储无限的小数是不可能保证精确的</div>
  <br>
  <div>1.使用 toPrecision 凑整并 parseFloat 转成数字后再显示</div>
  <div>2.做法是把小数转成整数后再运算。</div>
  <script>
    function strip(num, precision = 12) {
      return +parseFloat(num.toPrecision(precision));
    }
    strip(1.4000000000000001)


    /**
     * 精确加法
     */
    function add(num1, num2) {
      const num1Digits = (num1.toString().split('.')[1] || '').length;
      const num2Digits = (num2.toString().split('.')[1] || '').length;
      const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
      return (num1 * baseNum + num2 * baseNum) / baseNum;
    }
  </script>
</body>
</html>